﻿using System.Collections;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.Json.Serialization;
using Newtonsoft.Json;

namespace Devonline.Core;

public static class TypeExtensions
{
    #region 获取和判断类型
    /// <summary>
    /// 是否为可空类型
    /// TODO 在启用可空引用时待验证
    /// </summary>
    /// <param name="type">待判断的类型</param>
    /// <returns>判断结果</returns>
    public static bool IsNullable([DisallowNull] this Type type)
    {
        return (!type.IsValueType) || (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>));
    }
    /// <summary>
    /// 获取类型的核心类型, 用于判断可空类型的基本类型
    /// TODO 在启用可空引用时待验证
    /// </summary>
    /// <param name="type">原始类型</param>
    /// <returns>核心类型</returns>
    public static Type GetCoreType([DisallowNull] this Type type) => IsNullable(type) ? (Nullable.GetUnderlyingType(type) ?? type) : type;
    /// <summary>
    /// 获取泛型类型的泛型参数类型
    /// </summary>
    /// <param name="type">原始类型</param>
    /// <returns>泛型参数类型</returns>
    public static Type? GetGenericType([DisallowNull] this Type type)
    {
        if (!type.IsGenericType)
        {
            Type? baseType = type.BaseType;

            do
            {
                baseType = baseType?.BaseType;
            }
            while (baseType != null && baseType.BaseType != null && !baseType.IsGenericType);

            if (baseType != null && baseType.IsGenericType)
            {
                type = baseType;
            }
        }

        if (type.IsGenericType)
        {
            return type.GenericTypeArguments?.FirstOrDefault()?.GetCoreType();
        }

        return type.GetCoreType();
    }
    /// <summary>
    /// get the most inner base type of a type
    /// </summary>
    /// <param name="type">type instance</param>
    /// <returns>the most inner type</returns>
    public static Type? GetBaseType([DisallowNull] this Type type)
    {
        if (type?.BaseType != null)
        {
            return type.BaseType.GetBaseType();
        }

        return type;
    }
    /// <summary>
    /// to judge a type is from type or inherit from type 
    /// </summary>
    /// <param name="type"></param>
    /// <param name="from"></param>
    /// <returns>bool</returns>
    public static bool IsFromType(this Type type, Type from) => type.IsAssignableTo(from);
    /// <summary>
    /// to judge a type is from type or inherit from type 
    /// </summary>
    /// <param name="type"></param>
    /// <typeparam name="TType">from type 的类型参数</typeparam>
    /// <returns>bool</returns>
    public static bool IsFromType<TType>([DisallowNull] this Type type) => type.IsAssignableTo(typeof(TType));
    /// <summary>
    /// 判断一个类型是否一个集合类型
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static bool IsCollection([DisallowNull] this Type type) => type.IsCollectible || type.IsFromType<IEnumerable>();
    /// <summary>
    /// 判断一个类型是否泛型类型 
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static bool IsGenericType([DisallowNull] this Type type)
    {
        if (type.IsGenericType)
        {
            return true;
        }

        if (type.BaseType == null)
        {
            return false;
        }

        return type.BaseType.IsGenericType();
    }
    /// <summary>
    /// 返回一个类型是否基本数据类型
    /// 基础数据类型是指语言内置的基本值类型的数据类型
    /// 也即 TypeCode 从 Boolean 到 Decimal 的
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static bool IsBasicType([DisallowNull] this Type type) => Type.GetTypeCode(type) switch
    {
        >= TypeCode.Boolean and <= TypeCode.Decimal => true,
        _ => false
    };
    /// <summary>
    /// 返回一个类型是否是除 object 和 dynamic 以外的内置数据类型
    /// 这两种数据类型对于判断无意义
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static bool IsBuiltInType([DisallowNull] this Type type) => Type.GetTypeCode(type) switch
    {
        >= TypeCode.Boolean and <= TypeCode.Decimal => true,
        TypeCode.String => true,
        _ => false
    };
    /// <summary>
    /// 返回一个类型是否简单类型
    /// 此处定义的简单类型指基本数据类型 + datetime + string 这两种可以在数据库中直接进行字段关系隐射的类型
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static bool IsSampleType([DisallowNull] this Type type) => Type.GetTypeCode(type) switch
    {
        >= TypeCode.Boolean and <= TypeCode.String => true,
        _ => false
    };

    /// <summary>
    /// 返回成员的真实类型
    /// </summary>
    /// <param name="member"></param>
    /// <returns></returns>
    public static Type GetMemberType([DisallowNull] this MemberInfo member) => member switch
    {
        PropertyInfo propertyInfo => propertyInfo.PropertyType,
        FieldInfo fieldInfo => fieldInfo.FieldType,
        Type type => type,
        _ => member.GetType()
    };
    #endregion

    #region 获取字段/属性的特性相关扩展方法
    /// <summary>
    /// 获取对象上的显示名称 (Display 或 DisplayName 或 Description 特性的值)
    /// </summary>
    /// <param name="member">待获取对象</param>
    /// <returns>显示名称</returns>
    public static string GetDisplayName([DisallowNull] this MemberInfo member) => member.GetCustomAttribute<DisplayAttribute>()?.Name ?? member.GetCustomAttribute<DisplayNameAttribute>()?.DisplayName ?? member.GetCustomAttribute<DescriptionAttribute>()?.Description ?? member.Name;
    /// <summary>
    /// 通过当前类型的公开实例成员获取成员标注的 Display/DisplayName 特性的值
    /// </summary>
    /// <param name="type"></param>
    /// <param name="memberName"></param>
    /// <returns></returns>
    public static string? GetDisplayName([DisallowNull] this Type type, string memberName) => type.GetMember(memberName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)?.FirstOrDefault()?.GetDisplayName();
    /// <summary>
    /// 获取对象上的隐射到数据库的字段名字(Column 特性的 Name 值)
    /// </summary>
    /// <param name="member">待获取成员</param>
    /// <returns>字段名称</returns>
    public static string GetColumnName([DisallowNull] this MemberInfo member) => member.GetCustomAttribute<ColumnAttribute>()?.Name ?? member.Name;
    /// <summary>
    /// 获取对象上的隐射到数据库的字段名字(Table 特性的 Name 值)
    /// </summary>
    /// <param name="member">待获取成员</param>
    /// <returns>字段名称</returns>
    public static string GetTableName([DisallowNull] this MemberInfo member) => member.GetCustomAttribute<TableAttribute>()?.Name ?? member.Name;
    /// <summary>
    /// 获取类型字段设置的 json 序列化字段名
    /// </summary>
    /// <param name="member">待获取成员</param>
    /// <returns></returns>
    public static string GetJsonPropertyName([DisallowNull] this MemberInfo member) => member.GetCustomAttribute<JsonPropertyAttribute>()?.PropertyName ?? member.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name ?? member.Name;
    /// <summary>
    /// 获取类型字段设置的 json 序列化字段名
    /// </summary>
    /// <param name="type"></param>
    /// <param name="memberName">待获取成员</param>
    /// <returns></returns>
    public static string? GetJsonPropertyName([DisallowNull] this Type type, string memberName) => type.GetMember(memberName)?.FirstOrDefault()?.GetJsonPropertyName();
    /// <summary>
    /// 获取类型成员设定的缩写值
    /// </summary>
    /// <param name="member">待获取成员</param>
    /// <returns></returns>
    public static string GetAbbreviation([DisallowNull] this MemberInfo member) => member.GetCustomAttribute<AbbreviationAttribute>()?.Value ?? member.Name;
    /// <summary>
    /// 获取类型成员设定的缩写值
    /// </summary>
    /// <param name="type"></param>
    /// <param name="memberName">待获取成员</param>
    /// <returns></returns>
    public static string? GetAbbreviation([DisallowNull] this Type type, string memberName) => type.GetMember(memberName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)?.FirstOrDefault()?.GetAbbreviation();
    /// <summary>
    /// 获取类型成员设定的农历值
    /// </summary>
    /// <param name="member">待获取成员</param>
    /// <returns></returns>
    public static string GetLunisolarCalendar([DisallowNull] this MemberInfo member) => member.GetCustomAttribute<LunisolarCalendarAttribute>()?.Value ?? member.GetDisplayName();
    /// <summary>
    /// 获取类型成员设定的农历值
    /// </summary>
    /// <param name="type"></param>
    /// <param name="memberName">待获取成员</param>
    /// <returns></returns>
    public static string? GetLunisolarCalendar([DisallowNull] this Type type, string memberName) => type.GetMember(memberName, BindingFlags.Public | BindingFlags.Instance)?.FirstOrDefault()?.GetLunisolarCalendar();
    /// <summary>
    /// 获取类型成员设定的解释说明内容
    /// 该特性用于提供成员的详细解释说明
    /// </summary>
    /// <param name="member">待获取成员</param>
    /// <returns></returns>
    public static string GetExplanation([DisallowNull] this MemberInfo member) => member.GetCustomAttribute<ExplanationAttribute>()?.Value ?? member.GetDisplayName();
    /// <summary>
    /// 获取类型成员设定的解释说明内容
    /// </summary>
    /// <param name="type"></param>
    /// <param name="memberName">待获取成员</param>
    /// <returns></returns>
    public static string? GetExplanation([DisallowNull] this Type type, string memberName) => type.GetMember(memberName, BindingFlags.Public | BindingFlags.Instance)?.FirstOrDefault()?.GetExplanation();

    /// <summary>
    /// 判断成员中是否包含特性
    /// </summary>
    /// <typeparam name="T">类型参数, Attribute 类型</typeparam>
    /// <param name="member">带判断成员</param>
    /// <param name="inherit">是否包含继承的特性</param>
    /// <returns>判断结果</returns>
    public static bool HasAttribute<T>([DisallowNull] this MemberInfo member, bool inherit = true) where T : Attribute => member.IsDefined(typeof(T), inherit);
    /// <summary>
    /// 获取成员特性的指定属性值
    /// TODO TBC 可以使用字段选择器优化性能
    /// </summary>
    /// <param name="member">待获取对象</param>
    /// <param name="propertyName">用于获取值的特性上的属性名称</param>
    /// <returns>显示名称</returns>
    public static TValue? GetAttributeValue<TAttribute, TValue>([DisallowNull] this MemberInfo member, string propertyName) where TAttribute : Attribute
    {
        var result = member?.GetCustomAttribute<TAttribute>()?.GetPropertyValue(propertyName);
        return result == null ? default : (TValue)result;
    }

    /// <summary>
    /// 获取属性上设置的 excel 特性内容
    /// </summary>
    /// <param name="propertyInfo"></param>
    /// <returns></returns>
    public static ExcelAttribute? GetExcelAttribute([DisallowNull] this PropertyInfo propertyInfo)
    {
        var attribute = propertyInfo.GetCustomAttribute<ExcelAttribute>(true) ?? new();
        attribute.Field ??= propertyInfo;
        var name = propertyInfo.GetAttributeValue<DisplayAttribute, string>(nameof(DisplayAttribute.Name))
            ?? propertyInfo.GetAttributeValue<DisplayNameAttribute, string>(nameof(DisplayNameAttribute.DisplayName))
            ?? propertyInfo.GetAttributeValue<DescriptionAttribute, string>(nameof(DescriptionAttribute.Description));
        attribute.Name ??= name ?? attribute.Field.Name;
        attribute.Required = (attribute.Field != null && (!propertyInfo.PropertyType.IsNullable())) || propertyInfo.HasAttribute<RequiredAttribute>();
        attribute.ExportType ??= propertyInfo.PropertyType.GetCoreType();
        var propertyType = attribute.ExportType!;

        switch (Type.GetTypeCode(propertyType))
        {
            case TypeCode.DateTime:
                attribute.Format ??= AppSettings.DEFAULT_DATETIME_FORMAT;
                attribute.Size = attribute.Size <= 0 ? AppSettings.DEFAULT_EXCEL_DATETIME_SIZE : attribute.Size;
                break;
            case TypeCode.Byte:
            case TypeCode.SByte:
            case TypeCode.UInt16:
            case TypeCode.Int16:
            case TypeCode.UInt32:
            case TypeCode.Int32:
            case TypeCode.UInt64:
            case TypeCode.Int64:
                attribute.Format ??= AppSettings.DEFAULT_EXCEL_NUMBER_FORMAT;
                attribute.Size = attribute.Size <= 0 ? AppSettings.DEFAULT_EXCEL_NUMBER_SIZE : attribute.Size;
                break;
            case TypeCode.Single:
            case TypeCode.Double:
            case TypeCode.Decimal:
                attribute.Format ??= AppSettings.DEFAULT_EXCEL_DECIMAL_FORMAT;
                attribute.Size = attribute.Size <= 0 ? AppSettings.DEFAULT_EXCEL_DECIMAL_SIZE : attribute.Size;
                break;
            case TypeCode.Empty:
            case TypeCode.Boolean:
            case TypeCode.Char:
                attribute.Format ??= AppSettings.DEFAULT_EXCEL_STRING_FORMAT;
                attribute.Size = attribute.Size <= 0 ? AppSettings.DEFAULT_EXCEL_NUMBER_SIZE : attribute.Size;
                break;
            case TypeCode.DBNull:
            case TypeCode.Object:
            case TypeCode.String:
            default:
                attribute.Format ??= AppSettings.DEFAULT_EXCEL_STRING_FORMAT;
                attribute.Size = attribute.Size <= 0 ? AppSettings.DEFAULT_EXCEL_STRING_SIZE : attribute.Size;
                attribute.MaxLength = propertyInfo.GetCustomAttribute<MaxLengthAttribute>()?.Length ?? 0;
                break;
        }

        if (propertyType.IsEnum || propertyType == typeof(bool))
        {
            attribute.ExportType = typeof(string);
            attribute.Format ??= AppSettings.DEFAULT_EXCEL_STRING_FORMAT;
            attribute.Size = attribute.Size <= 0 ? AppSettings.DEFAULT_EXCEL_COLUMN_WIDTH : attribute.Size;
        }

        return attribute;
    }

    /// <summary>
    /// 获取属性或字段的 field 描述
    /// </summary>
    /// <param name="memberInfo"></param>
    /// <returns></returns>
    public static FieldAttribute GetFieldAttribute([DisallowNull] this PropertyInfo memberInfo)
    {
        var attribute = memberInfo.GetCustomAttribute<FieldAttribute>(true) ?? new FieldAttribute();
        attribute.Property = memberInfo;
        attribute.Name ??= memberInfo.Name;
        attribute.Doc ??= memberInfo.GetDisplayName();
        if (attribute.Type == TypeCode.Empty)
        {
            attribute.Type = Type.GetTypeCode(memberInfo.DeclaringType);
        }

        attribute.Size = attribute.Type switch
        {
            TypeCode.Boolean or TypeCode.Byte or TypeCode.SByte => 1,
            TypeCode.Char or TypeCode.Int16 or TypeCode.UInt16 => 2,
            TypeCode.Int32 or TypeCode.UInt32 or TypeCode.Single => 4,
            TypeCode.Int64 or TypeCode.UInt64 or TypeCode.Double or TypeCode.Decimal => 8,
            _ => attribute.Size
        };

        return attribute;
    }
    /// <summary>
    /// 获取类型的所有字段 field 特性值
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static IEnumerable<FieldAttribute> GetFieldAttributes([DisallowNull] this Type type) => type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.HasAttribute<FieldAttribute>()).Select(x => x.GetFieldAttribute());
    #endregion

    #region Lambda 表达式生成
    /// <summary>
    /// 获取类型的成员选择表达式, 形如: arg => arg.fieldName
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <typeparam name="TResult">成员类型</typeparam>
    /// <param name="memberInfo">成员</param>
    /// <returns></returns>
    public static Expression<Func<T, TResult>> GetMemberExpression<T, TResult>(this MemberInfo memberInfo)
    {
        var parameterExpression = Expression.Parameter(typeof(T), AppSettings.DEFAULT_LAMBDA_PARAMETER);
        var memberExpression = Expression.MakeMemberAccess(parameterExpression, memberInfo);
        return Expression.Lambda<Func<T, TResult>>(memberExpression, parameterExpression);
    }
    /// <summary>
    /// 获取类型的成员相等表达式, 形如: arg => arg.fieldName == value
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <typeparam name="TResult">成员类型</typeparam>
    /// <param name="memberInfo">成员</param>
    /// <returns></returns>
    public static Expression<Func<T, bool>> GetMemberEqualExpression<T, TResult>(this MemberInfo memberInfo, TResult value)
    {
        var parameterExpression = Expression.Parameter(typeof(T), AppSettings.DEFAULT_LAMBDA_PARAMETER);
        var memberExpression = Expression.MakeMemberAccess(parameterExpression, memberInfo);
        var valueExpression = Expression.Constant(value);
        var equalExpression = Expression.Equal(memberExpression, valueExpression);
        return Expression.Lambda<Func<T, bool>>(equalExpression, parameterExpression);
    }
    /// <summary>
    /// 获取类型的成员赋值表达式, 形如: arg => arg.fieldName = value
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <typeparam name="TResult">成员类型</typeparam>
    /// <param name="memberInfo">成员</param>
    /// <returns></returns>
    public static Expression<Action<T>> GetMemberAssignExpression<T, TResult>(this MemberInfo memberInfo, TResult value)
    {
        var parameterExpression = Expression.Parameter(typeof(T), AppSettings.DEFAULT_LAMBDA_PARAMETER);
        var memberExpression = Expression.MakeMemberAccess(parameterExpression, memberInfo);
        var valueExpression = Expression.Constant(value);
        var assignExpression = Expression.Assign(memberExpression, valueExpression);
        return Expression.Lambda<Action<T>>(assignExpression, parameterExpression);
    }

    /// <summary>
    /// 获取类型的字符串类型成员选择表达式, 形如: arg => arg.fieldName
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="memberInfo">成员</param>
    /// <returns></returns>
    public static Expression<Func<T, string>> GetMemberExpression<T>(this MemberInfo memberInfo)
    {
        if (memberInfo.GetMemberType() != typeof(string))
        {
            throw new ArgumentException("member type must be string!");
        }

        return memberInfo.GetMemberExpression<T, string>();
    }
    /// <summary>
    /// 获取类型的字符串类型成员相等表达式, 形如: arg => arg.fieldName == value
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="memberInfo">成员</param>
    /// <returns></returns>
    public static Expression<Func<T, bool>> GetMemberEqualExpression<T>(this MemberInfo memberInfo, string value)
    {
        if (memberInfo.GetMemberType() != typeof(string))
        {
            throw new ArgumentException("member type must be string!");
        }

        return memberInfo.GetMemberEqualExpression<T, string>(value);
    }
    /// <summary>
    /// 获取类型的字符串类型成员赋值表达式, 形如: arg => arg.fieldName = value
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="memberInfo">成员</param>
    /// <returns></returns>
    public static Expression<Action<T>> GetMemberAssignExpression<T>(this MemberInfo memberInfo, string value)
    {
        if (memberInfo.GetMemberType() != typeof(string))
        {
            throw new ArgumentException("member type must be string!");
        }

        return memberInfo.GetMemberAssignExpression<T, string>(value);
    }
    #endregion

    #region 反射获取对象和调用方法
    /// <summary>
    /// 获取类型的实例
    /// </summary>
    /// <param name="type"></param>
    /// <param name="parameters"></param>
    /// <returns></returns>
    public static object? CreateInstance([DisallowNull] this Type type, params object[] parameters) => Activator.CreateInstance(type, parameters);
    /// <summary>
    /// 反射调用类型的静态泛型方法
    /// </summary>
    /// <param name="type">调用类型</param>
    /// <param name="methodName">方法名</param>
    /// <param name="parameters">参数列表</param>
    /// <param name="returnValue">返回值</param>
    /// <param name="genericTypes">泛型类型</param>
    public static void InvokeGenericMethod([DisallowNull] this Type type, string methodName, object[] parameters, out object? returnValue, params Type[] genericTypes)
    {
        returnValue = null;
        var methodInfo = type?.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).FirstOrDefault(x => x.IsGenericMethod && x.Name == methodName && x.GetParameters().Length == (parameters?.Length ?? 0));
        if (methodInfo != null)
        {
            returnValue = methodInfo.MakeGenericMethod(genericTypes).Invoke(null, parameters);
        }
    }
    /// <summary>
    /// 反射调用类型的静态泛型方法
    /// </summary>
    /// <typeparam name="T">返回值类型</typeparam>
    /// <param name="type">调用类型</param>
    /// <param name="methodName">方法名</param>
    /// <param name="parameters">参数列表</param>
    /// <param name="genericTypes">泛型类型</param>
    /// <returns>返回调用结果</returns>
    public static T? InvokeGenericMethod<T>([DisallowNull] this Type type, string methodName, object[] parameters, params Type[] genericTypes) where T : class
    {
        var methodInfo = type?.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).FirstOrDefault(x => x.IsGenericMethod && x.Name == methodName && x.GetParameters().Length == (parameters?.Length ?? 0));
        if (methodInfo != null)
        {
            var returnValue = methodInfo.MakeGenericMethod(genericTypes).Invoke(null, parameters);
            if (returnValue != null)
            {
                return (T)returnValue;
            }
        }

        return default;
    }
    /// <summary>
    /// 反射调用类型的泛型扩展方法
    /// 预处理调用者参数, 因此不需要传递调用者参数
    /// </summary>
    /// <param name="type">调用类型</param>
    /// <param name="methodName">方法名</param>
    /// <param name="caller">调用对象</param>
    /// <param name="parameters">参数列表</param>
    /// <param name="returnValue">返回值</param>
    /// <param name="genericTypes">泛型类型</param>
    public static void InvokeGenericMethod([DisallowNull] this Type type, string methodName, object caller, object[] parameters, out object? returnValue, params Type[] genericTypes)
    {
        returnValue = null;
        var methodInfo = type?.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).FirstOrDefault(x => x.IsGenericMethod && x.Name == methodName && x.GetParameters().Length == (parameters?.Length ?? 0) + 1);
        if (methodInfo != null)
        {
            var args = new List<object>
                {
                    caller
                };

            if (parameters.IsNotNullOrEmpty())
            {
                args.AddRange(parameters);
            }

            returnValue = methodInfo.MakeGenericMethod(genericTypes).Invoke(caller, args.ToArray());
        }
    }
    /// <summary>
    /// 反射调用类型的泛型扩展方法
    /// 预处理调用者参数, 因此不需要传递调用者参数
    /// </summary>
    /// <typeparam name="T">返回值类型</typeparam>
    /// <param name="type">调用类型</param>
    /// <param name="methodName">方法名</param>
    /// <param name="caller">调用对象</param>
    /// <param name="parameters">参数列表</param>
    /// <param name="genericTypes">泛型类型</param>
    /// <returns>返回调用结果</returns>
    public static T? InvokeGenericMethod<T>([DisallowNull] this Type type, string methodName, object caller, object[] parameters, params Type[] genericTypes) where T : class
    {
        var methodInfo = type?.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).FirstOrDefault(x => x.IsGenericMethod && x.Name == methodName && x.GetParameters().Length == (parameters?.Length ?? 0) + 1);
        if (methodInfo != null)
        {
            var args = new List<object> { caller };
            if (parameters.IsNotNullOrEmpty())
            {
                args.AddRange(parameters);
            }

            var returnValue = methodInfo.MakeGenericMethod(genericTypes).Invoke(caller, args.ToArray());
            if (returnValue != null)
            {
                return (T)returnValue;
            }
        }

        return default;
    }
    #endregion

    #region 其他获取成员的扩展方法
    /// <summary>
    /// 获取成员的业务类型 BusinessType
    /// </summary>
    /// <param name="member"></param>
    /// <returns></returns>
    public static string? GetBusinessType([DisallowNull] this MemberInfo member) => member.GetCustomAttribute<BusinessTypeAttribute>()?.Name ?? (member.ReflectedType?.Name + AppSettings.CHAR_DOT + member.Name);
    /// <summary>
    /// 获取类型的所有成员对应的业务类型 BusinessType
    /// 成员的所有业务类型中, 会始终包含一个由类型名组成的业务类型, 作为整个数据的通用业务类型
    /// </summary>
    /// <param name="type">调用类型</param>
    /// <returns></returns>
    public static IEnumerable<KeyValuePair<string, string>> GetBusinessTypes([DisallowNull] this Type type)
    {
        var businessTypes = new Dictionary<string, string> { { type.Name, type.Name } };
        var propertyInfos = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.HasAttribute<BusinessTypeAttribute>());
        if (propertyInfos != null && propertyInfos.Any())
        {
            foreach (var propertyInfo in propertyInfos)
            {
                businessTypes.Add(propertyInfo.Name, propertyInfo.GetBusinessType() ?? (type.Name + AppSettings.CHAR_DOT + propertyInfo.Name));
            }
        }

        return businessTypes;
    }
    /// <summary>
    /// 获取类型 TEntitySet 中类型为 TElement 的默认集合(第一个)
    /// </summary>
    /// <typeparam name="TEntitySet"></typeparam>
    /// <typeparam name="TElement"></typeparam>
    /// <param name="entitySet"></param>
    /// <returns></returns>
    public static IEnumerable<TElement>? GetCollectionMember<TEntitySet, TElement>([DisallowNull] this TEntitySet entitySet) where TEntitySet : class where TElement : class
    {
        var propertyInfo = entitySet.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(x => x.PropertyType.IsFromType<IEnumerable<TElement>>());
        return propertyInfo is not null && propertyInfo.GetValue(entitySet) is IEnumerable<TElement> collection ? collection : null;
    }
    /// <summary>
    /// 获取类型 TEntitySet 中类型为 TElement 的集合
    /// </summary>
    /// <typeparam name="TEntitySet"></typeparam>
    /// <typeparam name="TElement"></typeparam>
    /// <param name="entitySet"></param>
    /// <returns></returns>
    public static IEnumerable<KeyValuePair<string, IEnumerable<TElement>>> GetCollectionMembers<TEntitySet, TElement>([DisallowNull] this TEntitySet entitySet) where TEntitySet : class where TElement : class
    {
        var elements = new Dictionary<string, IEnumerable<TElement>>();
        var propertyInfos = entitySet.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType.IsFromType<IEnumerable<TElement>>());
        if (propertyInfos != null && propertyInfos.Any())
        {
            foreach (var propertyInfo in propertyInfos)
            {
                if (propertyInfo.GetValue(entitySet) is IEnumerable<TElement> collection)
                {
                    elements.Add(propertyInfo.Name, collection);
                }
            }
        }

        return elements;
    }

    /// <summary>
    /// 根据字段获取静态成员的值
    /// </summary>
    /// <param name="fieldInfo">字段</param>
    /// <returns></returns>
    public static TValue? GetStaticMemberValue<TValue>([DisallowNull] this FieldInfo fieldInfo)
    {
        var value = fieldInfo.GetValue(null);
        if (value is not null && value is TValue result)
        {
            return result;
        }

        return default;
    }
    /// <summary>
    /// 根据类型和字段名获取静态成员的值
    /// </summary>
    /// <param name="type">类型</param>
    /// <param name="fieldName">静态成员字段名</param>
    /// <returns></returns>
    public static TValue? GetStaticMemberValue<TValue>([DisallowNull] this Type type, string fieldName)
    {
        var fieldInfo = type.GetField(fieldName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.IgnoreCase);
        if (fieldInfo is not null)
        {
            return fieldInfo.GetStaticMemberValue<TValue>();
        }

        return default;
    }
    /// <summary>
    /// 根据字符串值获取静态成员的值
    /// </summary>
    /// <typeparam name="TValue">成员类型</typeparam>
    /// <param name="type">类型</param>
    /// <param name="value">字符串值</param>
    /// <returns></returns>
    public static TValue? GetStaticMemberValueByStringValue<TValue>([DisallowNull] this Type type, string value)
    {
        var fieldInfos = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.IgnoreCase);
        foreach (var fieldInfo in fieldInfos)
        {
            var fieldValue = fieldInfo.GetValue(null);
            if (fieldValue is TValue result && result.ToString() == value)
            {
                return result;
            }
        }

        return default;
    }
    #endregion
}